package com.shiku.imserver.message.hander;

import com.shiku.imserver.CoreService;
import com.shiku.imserver.common.annotation.MessageCommandAnnotation;
import com.shiku.imserver.common.constant.KConstants;
import com.shiku.imserver.common.hander.AbstractMessageHandler;
import com.shiku.imserver.common.message.AbstractMessage;
import com.shiku.imserver.common.message.ChatMessage;
import com.shiku.imserver.common.message.PacketVO;
import com.shiku.imserver.common.packets.ChatType;
import com.shiku.imserver.common.packets.ImPacket;
import com.shiku.imserver.common.proto.MessageProBuf;
import com.shiku.imserver.common.tcp.TcpPacket;
import com.shiku.imserver.common.utils.ProBufUtils;
import com.shiku.imserver.common.utils.StringUtils;
import com.shiku.imserver.message.MessageFactory;
import com.shiku.imserver.service.IMBeanUtils;
import cn.xyz.commons.constants.MsgType;
import com.shiku.utils.StringUtil;


import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;

import agora.media.RtcTokenBuilder;
import agora.media.RtcTokenBuilder.Role;
@Slf4j
public class SendMessageHandler extends AbstractMessageHandler {
   // private static final Logger logger = LoggerFactory.getLogger(SendMessageHandler.class);
	 static int expirationTimeInSeconds = 7200; 
    @MessageCommandAnnotation(command = 10)
    public PacketVO sendMsgMessageHandler(ImPacket packet, ChannelContext channelContext) {
    	log.info("[ww]sendMsgMessageHandler");
        try {
            ChatMessage message = (ChatMessage) ProBufUtils.decoderMessageBody(packet.getBytes(), MessageProBuf.ChatMessage.getDescriptor(), ChatMessage.class);
            log.info("[ww]sendMsgMessageHandler,message.getType()="+message.getType()+",getToUserId="+message.getToUserId());
            byte chatType = message.getMessageHead().getChatType();
            //chatType   1===>单聊   2===>群聊
            if (KConstants.isDebug) {
            	log.info(" process msg => {}", message.toString());
            }
            //关键字过滤
            if (MsgType.TYPE_TEXT == message.getType() && IMBeanUtils.getImconfig().isFilterKeyWord()) {
                String keyWord = IMBeanUtils.getServiceRepository().filterKeyWord(message);
                if (!StringUtil.isEmpty(keyWord)) {
                	log.info(" filterKeyWord  true ", message.getContent());
                    return MessageFactory.createErrorPacket(message.getMessageHead(), (short)-2, keyWord);
                }
            }

            if (chatType == 3) {
                ChatMessage chatMessage = message.clone();
                chatMessage.getMessageHead().setChatType((byte) 1);
                TcpPacket tcpPacket = ProBufUtils.encodeTcpPacket(chatMessage, MessageProBuf.ChatMessage.getDescriptor());
                tcpPacket.setCommand((short)10);
                Tio.sendToAll(channelContext.groupContext, tcpPacket);
                Tio.send(channelContext, MessageFactory.createSuccessIMPacket(message));
                IMBeanUtils.getRocketmqService().offMessagePush(message);
                return null;
            }
            String from = message.getMessageHead().getFrom();
            String to = message.getMessageHead().getTo();
            if (StringUtils.isEmpty(from) || StringUtils.isEmpty(to)) {
            	log.error(" from or to is null");
                return null;
            }
            String sender = CoreService.parseBareUserId(from);
            String receiver = CoreService.parseBareUserId(to);
            String fromResource = CoreService.parseResource(from);
            packet.setMessage(message);
            //log.info("chatmsg readDelTime="+message.getReadDelTimeLength());
            //log.info("发起通话2 getAgoraAppID => {},content={}",IMBeanUtils.getImconfig().getAgoraAppID(),message.getContent());
            if (chatType == 1) {
            	log.info("getType => {}",message.getType());
            	if(message.getType()==MsgType.TYPE_IS_CONNECT_VOICE){
            		RtcTokenBuilder token = new RtcTokenBuilder();
            		int timestamp = (int)(System.currentTimeMillis() / 1000 + expirationTimeInSeconds);
            		
            		log.info("发起通话 getAgoraAppID => {},content={}",IMBeanUtils.getImconfig().getAgoraAppID(),message.getContent());
            		
            		String szToken = token.buildTokenWithUserAccount( IMBeanUtils.getImconfig().getAgoraAppID(), IMBeanUtils.getImconfig().getAgoraToken(),  
            				message.getFromUserId(), message.getToUserId(), Role.Role_Publisher, timestamp);
            		message.setContent(IMBeanUtils.getImconfig().getAgoraAppID()+"|"+szToken);
            		
            		
            	}
            	if(message.getType()==MsgType.TYPE_CONNECT_VOICE)
            	{
            		RtcTokenBuilder token = new RtcTokenBuilder();
            		int timestamp = (int)(System.currentTimeMillis() / 1000 + expirationTimeInSeconds);
            		log.info("接收通话 getAgoraAppID => {}，ID={}",IMBeanUtils.getImconfig().getAgoraAppID(),message.getToUserId());
            		String szToken = token.buildTokenWithUserAccount( IMBeanUtils.getImconfig().getAgoraAppID(), IMBeanUtils.getImconfig().getAgoraToken(),  
            				message.getToUserId(), message.getToUserId(), Role.Role_Publisher, timestamp);
            		message.setContent(IMBeanUtils.getImconfig().getAgoraAppID()+"|"+szToken);
            	}

            	 ImPacket SendPacket = MessageFactory.convertToImPacket(message);
            	//log.info("发起通话2 getAgoraAppID => {},content={}",IMBeanUtils.getImconfig().getAgoraAppID(),message.getContent());
                //Tio.send(channelContext,SendPacket);

            	//发送服务端接收到消息到回执
                Tio.send(channelContext, MessageFactory.createSuccessIMPacket(message));
                boolean bHaveMsg = IMBeanUtils.getRedisService().queryMessage(message.getMessageHead().getMessageId(),message.getFromUserId(),message.getToUserId());
                    if(bHaveMsg) {
                    log.info(" 客户端同一条消息重复发了，开启过滤~~~");
                    return null;
                }
                //申请加好友
                if(message.getType()==MsgType.TYPE_SAYHELLO )
                {
                   Boolean isExistsSayHello = IMBeanUtils.getRedisService().isExistsSayHello(message.getFromUserId(),message.getToUserId());
                    if(isExistsSayHello) return null;
                    IMBeanUtils.getRedisService().saveSayHello(message.getFromUserId(),message.getToUserId());
                }
                //同意加好友
                if(message.getType()==MsgType.TYPE_PASS)
                {

                    log.info("[ww]:TYPE_PASS UserId="+message.getToUserId()+",getFromUserId="+message.getFromUserId());
                    IMBeanUtils.getRedisService().delSayHello(message.getToUserId(),message.getFromUserId());

                    Boolean isExistsSayHello = IMBeanUtils.getRedisService().isExistsPass(message.getFromUserId(),message.getToUserId());
                    if(isExistsSayHello) return null;
                    IMBeanUtils.getRedisService().savePass(message.getFromUserId(),message.getToUserId());
                }
                IMBeanUtils.getRedisService().SaveMessage(message.getMessageHead().getMessageId(),message.getFromUserId(),message.getToUserId());

                boolean online = CoreService.userIsOnline(channelContext.groupContext, receiver);
                if (KConstants.isDebug) {
                	log.info(" 接收方 userId {} online => {}", receiver, Boolean.valueOf(online));
                }

                if (!online) {
                	//加好友消息，一个人只能入一条
                	if(message.getType()==MsgType.TYPE_SAYHELLO)
                	{
                		boolean  isExists =	IMBeanUtils.getMessageRepository().getChatOffMessageAddFirend(message.getFromUserId(),message.getToUserId());
                		if(!isExists)
                		{
                			log.info("对方不在线，离线加好友信息");
                			 IMBeanUtils.getRocketmqService().offMessagePush(message);
                             IMBeanUtils.getMessageRepository().storeChatOffMessage(message);
                             return null;
                		}
                	}
                	else {
                		IMBeanUtils.getRocketmqService().offMessagePush(message);
                        IMBeanUtils.getMessageRepository().storeChatOffMessage(message);
                	}
                } else if (sender.equals(receiver)) {
                    CoreService.sendToUserOtherResource(channelContext.groupContext, sender, channelContext.getId(), SendPacket, false);
                } else {
                     CoreService.sendToUser(channelContext.groupContext, to, SendPacket);
                    //发送有可能会发生失败，不会进入回调，提前存到缓存
                     IMBeanUtils.getRedisService().AddWillMessage(Integer.valueOf(to),message);
                }
                if (!sender.equals(receiver) && !"Server".equals(fromResource)) {
                    CoreService.sendToUserOtherResource(channelContext.groupContext, sender, channelContext.getId(), SendPacket, false);
                }
            } else if (chatType == 2) {
                if ("Server".equals(fromResource)) {
                    Tio.send(channelContext, MessageFactory.createSuccessIMPacket(message));

                }
            	String messageId = message.getMessageHead().getMessageId();
            	 log.info("[ww]:messageId="+messageId);
            	//同一个消息发多次，需要给他过滤
            	 ChatMessage _currMessage = IMBeanUtils.getRedisService().queryGroupMessage(messageId);
                 if (_currMessage != null) {
                	 log.info("[ww]:消息id重复了，过滤！");
                     return null;
                 }


                 IMBeanUtils.getRedisService().saveGroupMessage(message);
                 long _maxID =  IMBeanUtils.getRedisService().saveGroupMaxMsgID(message);
            	 
                log.info("[ww]:chatType == 2,_maxID="+_maxID);
           
           	  //数据包加入ChatMsgId,重新打包发到客户端
               message.setChatMsgId(_maxID);
              // message.setObjectId(  message.getMessageHead().getTo());
             
           	   ImPacket SendPacket = MessageFactory.convertToImPacket(message);
                log.info("[ww]sendMsgMessageHandler2,message.getType()="+message.getType()+",getToUserId="+message.getToUserId());
               Tio.sendToGroup(channelContext.groupContext, to, SendPacket);
               IMBeanUtils.getRocketmqService().offMessagePush(message);
            }
            IMBeanUtils.getMessageRepository().offerMessage(message);
            return null;
        } catch (Exception e) {
            e.printStackTrace();
        }
		return null;
    }
}
